from enum import Enum
import time
from log import *
class FRAME_STATE(Enum):
    # 定义状态常量
    STATE_WAIT_HEAD1 = 0
    STATE_WAIT_HEAD2 = 1
    STATE_WAIT_LEN = 2
    STATE_WAIT_PAYLOAD = 3
    STATE_WAIT_CRC = 4


class CommandParser:
    def __init__(self):
        self.rx_state = FRAME_STATE.STATE_WAIT_HEAD1
        self.data_len = 0
        self.recv_count = 0
        self.frame_buf = [0] * 256
        self.last_time = 0

        # 假设的头部字节值（根据实际协议修改）
        self.HEAD1_VALUE = 0x55  # 示例值
        self.HEAD2_VALUE = 0xAA  # 示例值
        self.ok = False

    def cmd(self, byte):
        self.ok = False
        current_time = int(time.time() * 1000)  # 毫秒时间戳

        # 超时处理（10ms超时）
        time_diff = current_time - self.last_time
        # if time_diff > 10:
        #     if self.rx_state != FRAME_STATE.STATE_WAIT_HEAD1:
        #         self.rx_state = FRAME_STATE.STATE_WAIT_HEAD1

        self.last_time = current_time

        if self.rx_state == FRAME_STATE.STATE_WAIT_HEAD1:
            if byte == self.HEAD1_VALUE:
                self.rx_state = FRAME_STATE.STATE_WAIT_HEAD2

        elif self.rx_state == FRAME_STATE.STATE_WAIT_HEAD2:
            if byte == self.HEAD2_VALUE:
                self.rx_state = FRAME_STATE.STATE_WAIT_LEN
            else:
                self.rx_state = FRAME_STATE.STATE_WAIT_HEAD1

        elif self.rx_state == FRAME_STATE.STATE_WAIT_LEN:
            self.data_len = byte
            self.recv_count = 0
            self.rx_state = FRAME_STATE.STATE_WAIT_PAYLOAD

        elif self.rx_state == FRAME_STATE.STATE_WAIT_PAYLOAD:
            if self.recv_count < len(self.frame_buf):
                self.frame_buf[self.recv_count] = byte
                self.recv_count += 1

            if self.recv_count >= self.data_len:
                self.rx_state = FRAME_STATE.STATE_WAIT_CRC

        elif self.rx_state == FRAME_STATE.STATE_WAIT_CRC:
            # 计算校验和
            checksum = 0
            for i in range(self.data_len):
                checksum = (checksum + self.frame_buf[i]) & 0xFF

            if checksum == byte:
                self.ok = True
                #info(f"Received frame: length={self.data_len}, data={self.frame_buf[:self.data_len]}")
                #self._process_frame()

            else:
                print("error: checksum mismatch")

            self.rx_state = FRAME_STATE.STATE_WAIT_HEAD1

        else:
            self.rx_state = FRAME_STATE.STATE_WAIT_HEAD1

        return self.ok

    def process_frame(self):
        if self.ok:
            data = self.frame_buf[:self.data_len]
            checksum = data[self.data_len-1]
            ret = {
                "cmd": data[0],
                "result": data[1] if data else 0,
                "data": data,
                "checksum": checksum
            }
            self.reset()
            return ret
        else: return None

    def reset(self):
        """重置解析器状态"""
        self.rx_state = FRAME_STATE.STATE_WAIT_HEAD1
        self.data_len = 0
        self.recv_count = 0

# 枚举定义
class CMDType(Enum):
    CMD_DOWN_BOOT_DEFALUT = 1
    CMD_DOWN_SEED_SEND = 2
    CMD_DOWN_KEY = 3
    CMD_CHECK_FIRMWARE = 4
    CMD_ERASE_BACK_APP = 5
    CMD_DOWN_APP = 6
    CMD_CRC_CHECK = 7
    CMD_COPY_APP = 8
    CMD_END_APP = 9

class DownAPPState(Enum):
    DOWN_BOOT_DEFALUT = CMDType.CMD_DOWN_BOOT_DEFALUT.value
    DOWN_SEED_SEND = CMDType.CMD_DOWN_SEED_SEND.value
    DOWN_KEY = CMDType.CMD_DOWN_KEY.value
    CHECK_FIRMWARE = CMDType.CMD_CHECK_FIRMWARE.value
    ERASE_BACK_APP = CMDType.CMD_ERASE_BACK_APP.value
    DOWN_APP = CMDType.CMD_DOWN_APP.value
    CRC_CHECK = CMDType.CMD_CRC_CHECK.value
    COPY_APP = CMDType.CMD_COPY_APP.value
    END_APP = CMDType.CMD_END_APP.value



def read_bin_chunks(file_path, chunk_size=240):
    chunks = []
    with open(file_path, "rb") as f:
        while True:
            data = f.read(chunk_size)
            if not data:
                break
            chunks.append(data)
    return chunks


def parse_frame(frame: bytes):
    # 状态机状态定义
    STATE_WAIT_HEAD = 0
    STATE_WAIT_LEN = 1
    STATE_WAIT_DATA = 2
    STATE_WAIT_CHECKSUM = 3

    state = STATE_WAIT_HEAD
    buffer = bytearray()
    result = None

    for b in frame:
        if state == STATE_WAIT_HEAD:
            buffer.append(b)
            if len(buffer) == 2:
                if buffer[0] == 0x55 and buffer[1] == 0xAA:
                    state = STATE_WAIT_LEN
                else:
                    buffer.pop(0)  # 滑动窗口找帧头
        elif state == STATE_WAIT_LEN:
            length = b
            buffer.append(b)
            state = STATE_WAIT_DATA
            data_bytes_needed = length  # 包含 CMD+DATA
        elif state == STATE_WAIT_DATA:
            buffer.append(b)
            data_bytes_needed -= 1
            if data_bytes_needed == 0:
                state = STATE_WAIT_CHECKSUM
        elif state == STATE_WAIT_CHECKSUM:
            buffer.append(b)
            cmd = buffer[3]
            data = buffer[4:-1]
            checksum = buffer[-1]
            calc_sum = (cmd + sum(data)) & 0xFF
            if calc_sum != checksum:
                debug(f"校验错误: calc={calc_sum:02X}, recv={checksum:02X}")
            result = {
                "cmd": cmd,
                "result": data[0] if data else 0,
                "data": data,
                "checksum": checksum
            }
            break  # 已完整解析一帧

    return result


def get_frame(cmd: int, data: bytes) -> bytes:
    """
    :rtype: bytes
    """
    length = 1 + len(data)
    checksum = (cmd + sum(data)) & 0xFF
    frame = bytes([0xAA, 0x55, length, cmd]) + data + bytes([checksum])
    return frame
